package com.zhichat;

import com.zhichat.dao.SysConfigDao;
import com.zhichat.entity.SysConfigEntity;
import com.zhichat.infrastructure.redis.Keys;
import com.zhichat.infrastructure.redis.RedisRepository;
import com.zhichat.infrastructure.redis.rediskey.Key;
import com.zhichat.infrastructure.redis.rediskey.ZhiChat;
import com.zhichat.infrastructure.thread.ThreadPoolWorker;
import com.zhichat.web.socket.GlobalMsgHandle;
import com.zhichat.web.socket.netty.NettyWsInit;
import com.zhichat.web.vo.ws.MsgVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;

@Slf4j
@Component
@AllArgsConstructor
public class InitRunner implements ApplicationRunner, Ordered {

    private final RedisRepository redisRepository;
    private final SysConfigDao sysConfigDao;
    private final NettyWsInit nettyWsInit;
    private final RedissonClient redissonClient;
    private final GlobalMsgHandle globalMsgHandle;

    /**
     * ApplicationRunner 接口中的 run 方法会在 Spring Boot 启动完成后执行
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 初始化系统配置
        initSysConfig();
        // 启动netty服务
        ThreadPoolWorker.singleInstance().getExecutor().execute(nettyWsInit::start);
        // 监听 redisson topic 中的数据
        listenTopicData();
    }

    /**
     * 实现 Ordered 接口用于指定多个监听器的处理顺序。（这里只有一个）
     */
    @Override
    public int getOrder() {
        return 1;
    }

    /**
     * 初始化系统配置 -> redis
     */
    private void initSysConfig() {
        List<SysConfigEntity> SysConfigEntities = sysConfigDao.selectList(null);
        if (!CollectionUtils.isEmpty(SysConfigEntities)) {
            Key sysKey = new ZhiChat(Keys.SYS_KEY);
            redisRepository.set(sysKey, SysConfigEntities.get(0));
            log.info("系统配置初始化完成");
        }
    }


    /**
     * redisson 监听并处理 topic 中的数据
     * （注意：redisson 提供了一种简易实现的订阅发布，适用于访问量不大的情况，否则会使内存负担较重。）
     */
    private void listenTopicData() {
        try {
            log.info("redisson 监听topic：{}，启动成功", Keys.REDISSON_TOPIC_CHAT_MESSAGE_KEY);
            RTopic topic = redissonClient.getTopic(Keys.REDISSON_TOPIC_CHAT_MESSAGE_KEY);
            topic.addListener(MsgVO.class, (MsgVO, msg) -> {
//                log.info("收到消息:{}", JSON.toJSONString(msg));
                globalMsgHandle.sendMessage(msg);
            });
        } catch (Exception e) {
            log.error("redisson 监听topic：：{}，处理数据出现异常", Keys.REDISSON_TOPIC_CHAT_MESSAGE_KEY);
        }
    }
}
